package com.dlc.shop.multishop.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.dlc.shop.bean.dto.wukong.ChanneDeleteDTO;
import com.dlc.shop.bean.enums.LiveRoomStatusType;
import com.dlc.shop.common.response.ServerResponseEntity;
import com.dlc.shop.common.util.Json;
import com.dlc.shop.common.util.RedisUtil;
import com.dlc.shop.common.wukongim.constant.WuKongConstant;
import com.dlc.shop.live.common.constant.LiveCacheNames;
import com.dlc.shop.live.common.constant.MsgType;
import com.dlc.shop.live.common.service.LiveRoomProdService;
import com.dlc.shop.live.common.service.LiveRoomService;
import com.dlc.shop.live.common.vo.LiveMsgItem;
import com.dlc.shop.live.common.vo.LiveRoomProdVO;
import com.dlc.shop.live.common.vo.LiveRoomVO;
import com.dlc.shop.service.ImChannelService;
import com.dlc.shop.wukongim.service.WuKongImService;
import io.swagger.v3.oas.annotations.Hidden;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 *
 * @author TRACK
 */
@Hidden
@RestController
@RequestMapping("/notice/im")
@AllArgsConstructor
public class WuKongImNoticeController {
    private static final Logger logger = LoggerFactory.getLogger(WuKongImNoticeController.class);

    private final WuKongImService wuKongImService;
    private final LiveRoomService liveRoomService;
    private final ImChannelService imChannelService;
    private final LiveRoomProdService liveRoomProdService;

    /**
     * 直播间用户/客服在线情况回调
     */
    @RequestMapping("/online")
    public ServerResponseEntity<Void> notice(@RequestBody(required = false) String data,
                                               @RequestParam("event") String event) {
        if (!Objects.equals(event, WuKongConstant.USER_STATUS_WEBHOOK)) {
            // 只处理用户状态回调
            return ServerResponseEntity.success();
        }
        data = data.substring(1, data.length() - 1);
        // event user.onlinestatus
        // data数据格式：用户UID-设备标识-在线状态-连接ID-设备标识对应的设备在线数量-用户总个设备在线数量
        // ["LIVE_ANCHOR_1_56e4adf8ede948b38ca282aaa7aced0b-0-0-3-0-0","LIVE_ANCHOR_1_56e4adf8ede948b38ca282aaa7aced0b-0-1-5-1-1"]
        // ["LIVE_USER_85_39513c3e-1655-483d-b205-18c86e13f1ef-0-0-2542-0-0"]
        List<String> statusDataList = Arrays.stream(data.split(StrUtil.COMMA)).toList();
        List<String> dataStrList = new ArrayList<>(statusDataList.size());
        for (String dataStr : statusDataList) {
            dataStrList.add(dataStr.replace("\"", ""));
        }
        // 按uid分组
        Map<String, List<String>> statusDataMap = dataStrList.stream().collect(Collectors.groupingBy(s -> s.split(StrUtil.DASHED)[0]));
        for (String uid : statusDataMap.keySet()) {
            if (uid.startsWith(WuKongConstant.SHOP) || uid.startsWith(WuKongConstant.SYS)) {
                // 处理下客服在线状态，给在线的用户发送店铺/平台客服上下线消息
                Integer status = getStatus(statusDataMap, uid);
                if (status == 0) {
                    // 如果是离线 判断下当前是否有别的设备在线
                    Boolean userOnline = wuKongImService.getUserOnline(uid);
                    if (userOnline) {
                        // 有别的设备在线，不需要发送离线消息
                        continue;
                    }
                }
                // 这里商家和平台统一处理了，基于uid结构一致的基础上
                List<String> channelIds = imChannelService.listChannelByShopId(WuKongConstant.getShopIdByUid(uid));
                if (CollUtil.isNotEmpty(channelIds)) {
                    wuKongImService.messageSendbatch(uid + StrUtil.DASHED + status, channelIds, WuKongConstant.ONLINE_UPDATE);
                }
                continue;
            }
            if (!uid.startsWith(WuKongConstant.LIVE_ANCHOR) && !uid.startsWith(WuKongConstant.LIVE_USER)) {
                // 下面处理直播用户状态
                // 1.主播在线开播，离线暂停直播或关播
                // 2.直播间用户在线，直播间人数+1，离线则-1，直播间人数由redis维护，最长24小时，与直播间最长时间保持一致
                // 3.若主播离线关播，则将redis缓存的直播间人数删除
                continue;
            }
            handleLive(statusDataMap, uid);
        }
        return ServerResponseEntity.success();
    }

    private void handleLive(Map<String, List<String>> statusDataMap, String uid) {
        Integer status = getStatus(statusDataMap, uid);
        List<String> userList = statusDataMap.get(uid);
        boolean isDouble = userList.size() % 2 == 0;
        if (uid.startsWith(WuKongConstant.LIVE_ANCHOR) && !isDouble) {
            // 如果一次回调返回的同一个用户状态变化是偶数倍的，那么等同于他状态没发生变化，不做主播操作
            // 主播
            handleAnchor(uid, status);
        }
        if (uid.startsWith(WuKongConstant.LIVE_USER) && !isDouble) {
            // 如果一次回调返回的同一个用户状态变化是偶数倍的，那么等同于他状态没发生变化，不做人数增加
            // 用户
            String[] split = uid.substring(WuKongConstant.LIVE_USER.length()).split(WuKongConstant.UNDERLINE);
            Long roomId = Long.valueOf(split[0]);
            String channelId = WuKongConstant.LIVE_CHANNEL_PREFIX + roomId;
            // 改变直播间人数
            sendChangeLiveUserCountMsg(channelId, roomId, status > 0 ? 1 : -1);
            if (status <= 0) {
                // 移除订阅者
                wuKongImService.removeSubscriber(channelId, uid);
            } else {
                // 如果有商品是讲解状态，发送一条讲解消息给用户
                LiveRoomVO livingRoomInfo = liveRoomService.getLivingRoomInfo(null, roomId);
                sendProdExplainingMsg(livingRoomInfo, channelId, uid);
            }
        }
    }

    private void sendProdExplainingMsg(LiveRoomVO livingRoom, String channelId, String uid) {
        List<LiveRoomProdVO> prodList = liveRoomProdService.listLiveRoomProd(livingRoom.getRoomId());
        List<LiveRoomProdVO> livingProds = prodList.stream().filter(p -> Objects.equals(p.getExplainStatus(), 1)).toList();
        if (CollUtil.isNotEmpty(livingProds)) {
            LiveRoomProdVO liveRoomProdVO = livingProds.get(0);
            LiveMsgItem liveMsgItemParam = new LiveMsgItem();
            liveMsgItemParam.setMsgType(MsgType.EXPLAIN_STATUS);
            liveMsgItemParam.setProdId(liveRoomProdVO.getProdId());
            liveMsgItemParam.setExplainStatus(1);
            liveMsgItemParam.setCmd(WuKongConstant.EXPLAIN_STATUS);
            LiveMsgItem liveMsgItem = liveRoomProdService.handleLiveProd(liveMsgItemParam);
            wuKongImService.sendLiveRoomMessage(channelId, Json.toJsonString(liveMsgItem), uid);
        }
    }

    private static Integer getStatus(Map<String, List<String>> statusDataMap, String uid) {
        List<String> userList = statusDataMap.get(uid);
        userList.sort(Comparator.comparing(s -> s.split(StrUtil.DASHED)[3]));
        // 取最新连接情况
        String statusData = userList.get(userList.size() - 1);
        // 在线状态 0离线 1在线
        Integer status = Integer.parseInt(statusData.split(StrUtil.DASHED)[2]);
        return status;
    }

    private void handleAnchor(String uid, Integer status) {
        String[] split = uid.substring(WuKongConstant.LIVE_ANCHOR.length()).split(WuKongConstant.UNDERLINE);
        Long roomId = Long.valueOf(split[0]);
        String userId = split[1];
        if (status == 1) {
            LiveRoomVO livingRoom = liveRoomService.getLivingRoomInfo(userId, roomId);
            anchorOnline(livingRoom,WuKongConstant.LIVE_CHANNEL_PREFIX + roomId, roomId);
        } else {
            anchorClose(roomId, userId);
        }
    }

    /**
     * 发送直播间人数变化消息，内容为直播间在线人数
     */
    private void sendChangeLiveUserCountMsg(String channelId, Long roomId, Integer changeCount) {
        LiveMsgItem liveMsgItem = new LiveMsgItem();
        liveMsgItem.setMsgType(MsgType.LIVE_USER_COUNT);
        Integer count = liveRoomService.getLiveUserCount(roomId, changeCount);
        liveMsgItem.setLiveUserCount(count);
        liveMsgItem.setCmd(WuKongConstant.LIVE_USER_COUNT);
        wuKongImService.sendLiveRoomMessage(channelId, Json.toJsonString(liveMsgItem), null);
    }

    private void anchorOnline(LiveRoomVO livingRoom, String channelId, Long roomId) {
        long currentTimeMillis = System.currentTimeMillis();
        if (livingRoom.getStartTime().getTime() <= currentTimeMillis && livingRoom.getEndTime().getTime() >= currentTimeMillis
                && LiveRoomStatusType.isNeedOpen(livingRoom.getLiveStatus())) {
            // 更新直播为开播状态
            liveRoomService.updateLiveRoomStatus(LiveRoomStatusType.LIVING.value(), Collections.singletonList(livingRoom.getRoomId()));
            // 机器人发送消息通知用户直播状态变更
            LiveMsgItem statusMsg = new LiveMsgItem(WuKongConstant.LIVE_STATUS, LiveRoomStatusType.LIVING.value());
            wuKongImService.sendLiveRoomMessage(channelId, Json.toJsonString(statusMsg), null);
            liveRoomService.getLiveUserCount(roomId, 0);
        }
    }

    private void anchorClose(Long roomId, String userId) {
        String channelId = WuKongConstant.LIVE_CHANNEL_PREFIX + roomId;
        LiveRoomVO livingRoom = liveRoomService.getLivingRoomInfo(userId, roomId);
        if (Objects.isNull(livingRoom)) {
            return;
        }
        String liveAnchorUid = WuKongConstant.getLiveAnchorUid(userId, roomId);
        // 移除订阅者
        wuKongImService.removeSubscriber(channelId, liveAnchorUid);
        long currentTimeMillis = System.currentTimeMillis();
        if (livingRoom.getStartTime().getTime() <= currentTimeMillis && livingRoom.getEndTime().getTime() >= currentTimeMillis
                && Objects.equals(livingRoom.getLiveStatus(), LiveRoomStatusType.LIVING.value())) {
            logger.info("更新直播间状态为暂停" + livingRoom.getRoomId());
            // 更新直播为暂停状态
            liveRoomService.updateLiveRoomStatus(LiveRoomStatusType.STOP.value(), Collections.singletonList(livingRoom.getRoomId()));
            // 机器人发送消息通知用户直播状态变更
            LiveMsgItem statusMsg = new LiveMsgItem(WuKongConstant.LIVE_STATUS, LiveRoomStatusType.STOP.value());
            wuKongImService.sendLiveRoomMessage(channelId, Json.toJsonString(statusMsg), null);
        }
        if (livingRoom.getEndTime().getTime() <= currentTimeMillis
                && LiveRoomStatusType.isNeedFinish(livingRoom.getLiveStatus())) {
            logger.info("更新直播间状态为结束" + livingRoom.getRoomId());
            // 更新直播为结束状态
            liveRoomService.updateLiveRoomStatus(LiveRoomStatusType.FINISHED.value(), Collections.singletonList(livingRoom.getRoomId()));
            LiveMsgItem statusMsg = new LiveMsgItem(WuKongConstant.LIVE_STATUS, LiveRoomStatusType.FINISHED.value());
            wuKongImService.sendLiveRoomMessage(channelId, Json.toJsonString(statusMsg), null);
            // 删除频道
            wuKongImService.deleteChannel(new ChanneDeleteDTO(channelId, 2));
            // 删除观看人数缓存
            RedisUtil.del(LiveCacheNames.LIVE_CHANNEL_PERSON_COUNT + roomId);
        }
    }
}
